﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading.Tasks;

namespace SimpleReactiveObjects.Test.SimpleReactiveObjects
{
    [TestClass]
    public class ReactiveExpressionTest
    {
        [TestMethod]
        public void CreateTest1()
        {
            var never = Observable.Never<int>();
            var v1 = new ReactiveExpression<int>(never);
            v1.Value.Is(0);

            var singleton = Observable.Return(5.0);
            var v2 = new ReactiveExpression<double>(singleton);
            v2.Value.Is(5.0);
        }

        [TestMethod]
        public void CreateTest2()
        {
            var never = Observable.Never<int>();
            var v1 = never.ToReactiveExpression(10);
            v1.Value.Is(10);

            var singleton = Observable.Return(5.0);
            var v2 = singleton.ToReactiveExpression();
            v2.Value.Is(5.0);
        }


        [TestMethod]
        public void SubscribeTest()
        {
            var source = new Subject<int>();
            var v = new ReactiveExpression<int>(source);

            int? y = null;
            var yc = 0;
            v.Subscribe(x =>
            {
                y = x;
                yc++;
            });

            y.Is(0);
            yc.Is(1);

            int? z = null;
            var zc = 0;
            source.OnNext(10);
            v.Subscribe(x =>
            {
                z = x;
                zc++;
            });

            y.Is(10);
            z.Is(10);
            yc.Is(2);
            zc.Is(1);

            source.OnNext(10);

            y.Is(10);
            z.Is(10);
            yc.Is(2);
            zc.Is(1);
        }

        [TestMethod]
        public void DisposeTest()
        {
            var source = new Subject<int>();
            var v = new ReactiveExpression<int>(source);
            v.Value.Is(0);

            int? y = null;
            var yc = 0;
            var ycmp = false;
            v.Subscribe(x =>
            {
                y = x;
                yc++;
            },
            () => ycmp = true
            );

            source.OnNext(1);
            v.Value.Is(1);

            AssertEx.DoesNotThrow(() =>
            {
                v.Dispose();
            });

            AssertEx.DoesNotThrow(() =>
            {
                source.OnNext(10);
            });

            AssertEx.Throws<ObjectDisposedException>(() =>
            {
                v.Value.Is(1);
            });

            AssertEx.Throws<ObjectDisposedException>(() =>
            {
                v.Subscribe(x => { });
            });

            y.Is(1);
            yc.Is(2);
            ycmp.IsFalse();
        }
    }
}
